﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using Random = UnityEngine.Random;

namespace MouthAnimationFrame
{
    /// <summary>
    /// 口型动画实例
    /// </summary>
    [DisallowMultipleComponent]
    public class MouthAnimation : MonoBehaviour
    {
        #region 参数部分
        //对应的Animator
        public Animator mHeadAnimator;
        //对应需要播放声音的Event
        public string mAudioEvent;
        //播放声音的开始时间(对应播放口型的开始时间)
        public float mAudioPlayStartTime;
        //当前正在播放的口型动画的Hash Id
        public int mLipCurAnimStateId;
        public int mLipCurAnimStateIndex = 1;

        //当前播放状态
        private MouthAnimStatus curStatus = MouthAnimStatus.Stop;

        private bool isInit = false;

        public bool IsInit
        {
            get
            {
                return isInit;
            }
        }

        [SerializeField]
        private int _mouthLayerIndex;
        private bool _isOldMouthAnim; //旧版实现方式

        private bool _hadGetLayerIndex;
        #endregion

        #region 初始化
        //配置Animator的依赖
        public void InitMouthAnimation(Animator animator)
        {
            if (animator == null)
            {
                Debug.LogWarning("MouthAnimation.SetAnimator animator is null");
                return;
            }

            curStatus = MouthAnimStatus.Stop;

            mHeadAnimator = animator;

            MouthAnimationSyncHelper.GetInstance().RegisterMouthComponent(this);
            isInit = true;
        }
        #endregion

        #region 播放Event的入口与出口
        /// <summary>
        /// 开始播放对应的AudioEvent(实际上这里并没有播放音频,只是播放口型)
        /// </summary>
        /// <param name="audioEvent"></param>
        public void StartPlayingMouthAnimationSyncAudio(string audioEvent)
        {
            if (mHeadAnimator == null)
            {
                Debug.LogWarning("MouthAnimation.StartPlayingMouthAnimationSyncAudio mHeadAnimator is null");
                return;
            }

            if (!MouthAnimationSyncHelper.GetInstance().CheckMouthEventExist(audioEvent))
            {
                Debug.LogWarning("MouthAnimation.StartPlayingMouthAnimationSyncAudio audioEvent is not exist(or not initialized) " + audioEvent);
                return;
            }

            if (!_hadGetLayerIndex)
            {
                _hadGetLayerIndex = true;
                var animator = mHeadAnimator;
                var mouthLayerIndex = animator.GetLayerIndex("mouth");
                _isOldMouthAnim = animator.HasState(mouthLayerIndex, MouthAnimationSyncHelper.GetInstance().mLipSynchAnimStateId);
                _mouthLayerIndex = mouthLayerIndex;
            }

            mAudioEvent = audioEvent;
            mAudioPlayStartTime = Time.time;

            ChangeMouseAnimationStatus(MouthAnimStatus.Playing);
        }

        /// <summary>
        /// 停止当前组件下的MouthAnimation
        /// </summary>
        public void StopMouthAnimation()
        {
            if (mHeadAnimator == null || !IsInvoking()) return;

            CancelInvoke("TickMouthAnimationState");

            ChangeMouseAnimationStatus(MouthAnimStatus.Stop);
            mLipCurAnimStateId = MouthAnimationSyncHelper.GetInstance().mLipStopAnimStateId;
            mHeadAnimator.Play(mLipCurAnimStateId, _mouthLayerIndex);
        }

        #endregion

        #region 口型播放状态机

        /// <summary>
        /// 切换口型播放流程
        /// </summary>
        private void ChangeMouseAnimationStatus(MouthAnimStatus nextStatus)
        {
            if (curStatus == MouthAnimStatus.Stop)
            {
                StopToOther(nextStatus);
            }
            else if (curStatus == MouthAnimStatus.Playing)
            {
                PlayingToOther(nextStatus);
            }
            else if(curStatus == MouthAnimStatus.Pause)
            {
                PauseToOther(nextStatus);
            }
        }

        private void StopToOther(MouthAnimStatus nextStatus)
        {
            if (nextStatus == MouthAnimStatus.Stop) return;
            if(nextStatus == MouthAnimStatus.Playing)
            {
                curStatus = MouthAnimStatus.Playing;
                TickMouthAnimationState();
            }
        }

        private void PlayingToOther(MouthAnimStatus nextStatus)
        {
            if (nextStatus == MouthAnimStatus.Playing)
            {
                StopMouthAnimation();
                curStatus = MouthAnimStatus.Playing;
                TickMouthAnimationState();
            }
            else if(nextStatus == MouthAnimStatus.Stop)
            {
                curStatus = nextStatus;
            }
        }

        private void PauseToOther(MouthAnimStatus nextStatus)
        {

        }

        #endregion


        #region 播放对应的AudioEvent生命周期

        public void TickMouthAnimationState()
        {
            Profiler.BeginSample("LipSync1");
            if (this.gameObject)
            {
                //Debugger.LogError("TickMouthAnimationState " + Time.time);

                var ins = MouthAnimationSyncHelper.GetInstance();
                if (_isOldMouthAnim)
                {
                    //口型播放的时间 * 10：动画是30帧/s的，口型配置文件是3帧一个状态变化，也就是动画1s有10次状态变化
                    var index = Mathf.FloorToInt(Mathf.Max(Time.time - mAudioPlayStartTime, 0f) * 10f);

                    var result = ins.ShouldOpenMouth(mAudioEvent, index);
                    if (result != 0)
                    {
                        var stateName = result > 0 ? ins.mLipSynchAnimStateId : ins.mLipStopAnimStateId;
                        mHeadAnimator.Play(stateName, _mouthLayerIndex);

                        InternalTickMouthAnimationState();
                    }
                    else
                        StopMouthAnimation();
                }
                else
                {
                    //            if (mLipCurAnimStateId == 0 || mLipCurAnimStateId == ins.mLipStopAnimStateId || _normalizedTime > 1f)
                    //todo normalizedTime > 1 表示上一个动作播放结束。
                    if (mLipCurAnimStateId == 0 || mLipCurAnimStateId == ins.mLipStopAnimStateId || mHeadAnimator.GetCurrentAnimatorStateInfo(_mouthLayerIndex).normalizedTime > 1f)
                    {
                        //口型播放的时间 * 10：动画是30帧/s的，口型配置文件是3帧一个状态变化，也就是动画1s有10次状态变化
                        var index = Mathf.FloorToInt(Mathf.Max(Time.time - mAudioPlayStartTime, 0f) * 10f);

                        var result = ins.ShouldOpenMouth(mAudioEvent, index);

                        if (result != 0)
                        {
                            if (result > 0)
                            {
                                mLipCurAnimStateId = RandomMouthAnim();
                                if (mHeadAnimator.HasState(_mouthLayerIndex, mLipCurAnimStateId))
                                    mHeadAnimator.Play(mLipCurAnimStateId, _mouthLayerIndex);
                            }

                            InternalTickMouthAnimationState();
                        }
                        else
                            StopMouthAnimation();
                    }
                    else
                        InternalTickMouthAnimationState();
                }

            }

            Profiler.EndSample();
        }

        //没有用Update,直接使用了Invoke(每0.033秒Invoke一次),,,
        void InternalTickMouthAnimationState()
        {
            //        Debugger.LogError("InternalTickMouthAnimationState " + Time.time);
            //todo 按照30帧/s调用
            Invoke("TickMouthAnimationState", 0.033333f);
        }

        public int RandomMouthAnim()
        {
            var ins = MouthAnimationSyncHelper.GetInstance();
            var count = ins.mLipSyncAnimStateNameList.Count;
            if (count < 2)
                return ins.mLipSyncAnimStateNameList[0];

            int n = 1;
            if (mLipCurAnimStateIndex == 1 || (mLipCurAnimStateIndex != count && Random.Range(0f, 1f) > 0.5f))
                n = Random.Range(mLipCurAnimStateIndex + 1, count + 1);
            else
                n = Random.Range(1, mLipCurAnimStateIndex);

            mLipCurAnimStateIndex = n;
            return ins.mLipSyncAnimStateNameList[n - 1];
        }

        #endregion

        #region Unity生命周期

        private void OnDestroy()
        {
            if (MouthAnimationSyncHelper.GetInstance())
            {
                MouthAnimationSyncHelper.GetInstance().DisposeMouthComponent(this);
            }
        }

        #endregion

    }

}